package controllers;

import static play.data.Form.form;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import models.Chapitre;
import models.Choix;
import models.Matiere;
import models.NiveauQuestion;
import models.Qcm;
import models.QcmNiveauquestion;
import models.Question;
import models.Statut;
import models.Theme;
import models.Utilisateur;
import models.UtilisateurQcm;

import play.Logger;
import play.data.DynamicForm;
import play.data.Form;
import play.mvc.Controller;
import play.mvc.Result;
import play.mvc.Http.Session;


import views.html.modifierQcm.*;
import views.html.consultationQcm.detailQcmCree;
import views.html.pageErreurConnexion;

/**
 * . Controller qui permet à un expert de modifier un Qcm Il faut qu'il n'ait
 * jamais été passé
 * 
 * @author ELN1DY
 * 
 */
public abstract class ModifierQCM extends Controller {
	/**
	 * . Permet de lister les Qcm qui peuvent être modifié par l'expert connecté
	 * 
	 * @return la vue modifierQcm. Elle affiche la liste des qcms que l'expert
	 *         peut modifier
	 */
	public static Result listeQCM() {
		final Utilisateur us = Utilisateur.findById(Long.parseLong(session("id")));

		if (us.getStatut().equals(Statut.Etudiant)
				|| us.getStatut().equals(Statut.Administrateur)) {
			return ok(pageErreurConnexion.render());
		}

		List<Qcm> listeMesQcm = new ArrayList<Qcm>();
		final List<Qcm> listeQcmSupp = new ArrayList<Qcm>();
		listeMesQcm = us.getListeQcmCrees();

		for (Qcm qcm : listeMesQcm) {
			if (UtilisateurQcm.findAllByIdQcm(qcm.getIdQcm()).isEmpty()) {
				listeQcmSupp.add(qcm);
			}
		}
		return ok(modifierListeQcm.render(listeQcmSupp));
	}
	
	/**
	 * Enregistre l'id du Qcm qu'on veut modifier en session pour travailler
	 * dessus.
	 * @param id du Qcm qu'on veut modifier
	 * @return redirige vers le step 3 qui est la vue de la notation.
	 */
	public static Result modifierNotationQCM(final Long id){
		session().put("idQcmModifieNotation" , id.toString());
		String mess="notation";
		final Qcm qcm = Qcm.findById(id);
		return ok(modifierNotation.render(qcm, mess));
	}

	/**
	 * Enregistre l'id du Qcm qu'on veut modifier en session pour travailler
	 * dessus.
	 * @param id du Qcm qu'on veut modifier
	 * @return redirige vers le step 1 qui est la vue de la preimière étape.
	 */
	public static Result modifierQCM(final Long id) {
		session().put("idQcmModifié" , id.toString());
		return redirect(routes.ModifierQCM.step(1));
	}

	/**
	 * . Méthode qui permet d'afficher les vues suivantes et passer paramètres
	 * attendu dans chaque vue.
	 * 
	 * @param step
	 *            qui représente à quelle étape on est (sur 5)
	 * @return Renvoie la vue correspondant à l'étape suivante.
	 */
	public static Result step(final int step)throws ParseException {
		String mess=null;
		// Vérification que le Qcm appartient bien à l'Expert
				final long idUtilisateur = Long.parseLong(session().get("id"));
				final long idQcm = Long.parseLong(session().get("idQcmModifié"));
				final Qcm qcm = Qcm.findById(idQcm);
				final Form<Qcm> qcmForm = form(Qcm.class).fill(qcm);
				
				if (qcm.getUtilisateur().getIdUtilisateur()!=idUtilisateur){
					return ok(pageErreurConnexion.render());
				}
				
		switch (step) {

		// initialisation libelle date ouverture et cloture
		case 1:
			 
			return ok(modifierInitiateQcm.render(qcm));

			// liste des questions
		case 2:
			final List<Theme> allThemes = Theme.findAll();
			return ok(modifierAssocierQuestionQcm.render(qcm, allThemes));

			// Notation
		case 3:
			
			return ok(modifierNotation.render(qcm, mess));

		default:
			return forbidden();
		}

	}

	/**
	 * Envoie de chaque partie de la creation du QCM
	 */
	public static Result submit(final int step) {
		final DynamicForm filledForm = form().bindFromRequest();

		if (step == 1) {
			//Update de l'objet Qcm libelle, date ouverture, date fermeture
			toQcm1(filledForm);
			if ("home".equals(filledForm.field("action").value())) {
				return redirect(routes.Application.redirectionAccueil("Votre QCM est bien mis à jour"));
			} else {
			return redirect(routes.ModifierQCM.step(2));
			}
		}
		if (step == 2) {
			
			if ("retour".equals(filledForm.field("action").value())) {
				return redirect(routes.ModifierQCM.step(1));
			}
			//Update de l'objet Qcm question
			toQcm2(filledForm);
			
			final StringBuilder listeQuestion = getUtilisateurChoseQuestion();
			
			if ("home".equals(filledForm.field("action").value())) {
				return redirect(routes.Application.redirectionAccueil("Votre QCM est bien mis à jour"));
			}else {
				return redirect(routes.ModifierQCM.step(3));
			}
		}
		
		if (step == 3) {
			
			if ("retour".equals(filledForm.field("action").value())) {
				return redirect(routes.ModifierQCM.step(2));
			} else {
				// Update de la session grâce aux informations de notation
				toQcm3(filledForm);
				//Redirige vers la bonne page suivant si on vient de modifier un QCM ou modifier notation 
				
				if (session().containsKey("idQcmModifieNotation")) {
					Long idQcm=Long.parseLong(session().get("idQcmModifieNotation"));
					//Suppression de idQcmModifieNotation en session
					session().remove("idQcmModifieNotation");
					System.out.println(session());
					List<UtilisateurQcm> listeRep = UtilisateurQcm.findAllByIdQcm(idQcm);
					for(UtilisateurQcm userQcm : listeRep){
					    PasserQCM.calculNote(userQcm.getIdUtilisateurQcm());
					}
					return redirect(routes.ConsulterQCM.detailQcmCree(idQcm));
				}
				return redirect(routes.Application.redirectionAccueil("Votre QCM est bien mis à jour"));
			}
		}
		else return ok(pageErreurConnexion.render());
	}

	private static void toQcm1(DynamicForm filledForm) {
		final long idQcm = Long.parseLong(session().get("idQcmModifié"));
		final Qcm qcm = Qcm.findById(idQcm);
		qcm.setLibelle(filledForm.field("libelle").value());
		try {		
		qcm.setDateOuverture(Utile.stringToDate(filledForm.field("dateOuverture").value()));
		qcm.setDateCloture(Utile.stringToDate(filledForm.field("dateCloture").value()));
		} catch (ParseException e) {
			Logger.debug(e.toString());
		}
		Qcm.update(qcm);
		
	}
	/**
	 * Permet de faire un update des questions du qcm
	 * @param filledForm
	 */
	private static void toQcm2(DynamicForm filledForm) {
		final long idQcm = Long.parseLong(session().get("idQcmModifié"));
		final Qcm qcm = Qcm.findById(idQcm);
		List<Question> listeQuestions=new ArrayList<Question>();
		String listeIdQuestion = getUtilisateurChoseQuestion().toString();
		listeIdQuestion = listeIdQuestion.replaceAll("\\s", "");
		final String[] listeId = listeIdQuestion.split("#");
		for (int i = 0; i < listeId.length; i++) {
			final long idQuestion = Long.parseLong(listeId[i]);
			listeQuestions.add(Question.findById(idQuestion));
		}
		Set<Question> mySet = new HashSet<Question>(listeQuestions);
		List<Question> listeQuestions2 = new ArrayList<Question>(mySet); 
		qcm.setListeQuestions(listeQuestions2);
		Qcm.update(qcm);
	}
	
	private static void toQcm3(DynamicForm filledForm) {
		long idQcm;
		boolean modif = false;
		if(session().get("idQcmModifié")!=null){
			idQcm = Long.parseLong(session().get("idQcmModifié"));
			modif = true;
		}
		else idQcm = Long.parseLong(session().get("idQcmModifieNotation")); 
		final Qcm qcm = Qcm.findById(idQcm);
		for (int i=0; i<qcm.getListeNiveauQuestions().size(); i++){
			Long id = qcm.getListeNiveauQuestions().get(i).getIdQcmNiveauQuestion();
			String filledn=id.toString()+"n";
			String filledp=id.toString()+"p";
			qcm.getListeNiveauQuestions().get(i).setPointNegatif(Double.parseDouble(filledForm.field(filledn).value()));
			qcm.getListeNiveauQuestions().get(i).setPointPositif(Double.parseDouble(filledForm.field(filledp).value()));
		}
		// Récupération de la date d'aujourd'hui
		final GregorianCalendar today = new GregorianCalendar();
		qcm.setDateCreation(today.getTime());
		Qcm.update(qcm);
		session().clear();
		session().put("id", qcm.getUtilisateur().getIdUtilisateur().toString());
		session().put("cleQcm", qcm.getCleAuthentification());
		session().put("statut", qcm.getUtilisateur().getStatut().toString());
		if(modif=true){
			session().put("idQcmModifieNotation" , qcm.getIdQcm().toString());
			System.out.println(session());
		}
	}

	/**
	 * Concatene la liste des questions choisies
	 * 
	 * @param s
	 * @return
	 */
	private static StringBuilder getUtilisateurChoseQuestion() {
		final Map<String, String[]> urlFormEncoded = request().body()
				.asFormUrlEncoded();
		final StringBuilder listQuestions = new StringBuilder();
		if (urlFormEncoded != null) {
			for (String key : urlFormEncoded.keySet()) {
				final String[] value = urlFormEncoded.get(key);
				// on selectionne liste de Question
				if (value.length > 1) {
					for (int i = 0; i < value.length; i++) {
						listQuestions.append(value[i] + "#");
					}
					listQuestions.deleteCharAt(listQuestions.length() - 1);
				}
			}
		}
		return listQuestions;
	}

	/**
	 * Enregistre la liste des question dans le qcm
	 * 
	 * @param session
	 * @param qcm
	 * @return qcm
	 * @throws ParseException
	 */
	private static Qcm updateQcmNiveauQuestion(final Session session,
			final Qcm qcm) throws ParseException {
		final QcmNiveauquestion tempFacile = new QcmNiveauquestion();
		final QcmNiveauquestion tempMedium = new QcmNiveauquestion();
		final QcmNiveauquestion tempDifficile = new QcmNiveauquestion();
		final QcmNiveauquestion tempBonus = new QcmNiveauquestion();
		final List<QcmNiveauquestion> listeNiveauQuestions = new ArrayList<QcmNiveauquestion>();

		tempFacile.setNiveauQuestion(NiveauQuestion.findById(1L));
		tempMedium.setNiveauQuestion(NiveauQuestion.findById(2L));
		tempDifficile.setNiveauQuestion(NiveauQuestion.findById(3L));
		tempBonus.setNiveauQuestion(NiveauQuestion.findById(4L));

		tempFacile.setPointNegatif(Double.parseDouble(session.get("pnf")));
		tempFacile.setPointPositif(Double.parseDouble(session.get("ppf")));
		tempMedium.setPointNegatif(Double.parseDouble(session.get("pnm")));
		tempMedium.setPointPositif(Double.parseDouble(session.get("ppm")));
		tempDifficile.setPointNegatif(Double.parseDouble(session.get("pnd")));
		tempDifficile.setPointPositif(Double.parseDouble(session.get("ppd")));
		tempBonus.setPointNegatif(Double.parseDouble(session.get("pnb")));
		tempBonus.setPointPositif(Double.parseDouble(session.get("ppb")));

		listeNiveauQuestions.add(tempFacile);
		listeNiveauQuestions.add(tempMedium);
		listeNiveauQuestions.add(tempDifficile);
		listeNiveauQuestions.add(tempBonus);

		qcm.setListeNiveauQuestions(listeNiveauQuestions);
		return qcm;
	}

	/**
	 * Retourne la liste des Matières suivant un thème
	 * 
	 * @param idtheme
	 * @return
	 */
	public static Result getMatiere(final int idtheme) {
		// Vérification sur le Statut du Utilisateur afficher que si Statut=Expert
		final long idUtilisateur = Long.parseLong(session().get("id"));
		final Utilisateur temp = Utilisateur.findById(idUtilisateur);

		if (temp.getStatut().equals(Statut.Etudiant)) {
			return ok(pageErreurConnexion.render());
		}
		Theme t = new Theme();
		final Long idL = (long) idtheme;
		t = Theme.findById(idL);
		final List<Matiere> allMatiere = t.getSesMatieres();
		final StringBuilder list = new StringBuilder();
		for (int i = 0; i < allMatiere.size(); i++) {
			final Matiere m = allMatiere.get(i);
			list.append(m.getIdMatiere() + "#" + m.getLibelleM() + ";");
		}
		list.deleteCharAt(list.length() - 1);
		return ok(modifierListeMatiere.render(list.toString()));
	}

	/**
	 * Retourne la liste des Chapitre suivant une matière
	 * 
	 * @param idmatiere
	 * @return
	 */
	public static Result getChapitre(final int idmatiere) {
		// Vérification sur le Statut du Utilisateur afficher que si Statut=Expert
		final long idUtilisateur = Long.parseLong(session().get("id"));
		final Utilisateur temp = Utilisateur.findById(idUtilisateur);

		if (temp.getStatut().equals(Statut.Etudiant)) {
			return ok(pageErreurConnexion.render());
		}
		Matiere m = new Matiere();
		final Long idL = (long) idmatiere;
		m = Matiere.findById(idL);
		final List<Chapitre> allChapitre = m.getSesChapitres();
		final StringBuilder list = new StringBuilder();
		for (int i = 0; i < allChapitre.size(); i++) {
			final Chapitre c = allChapitre.get(i);
			list.append(c.getIdChapitre() + "#" + c.getLibelleC() + ";");
		}
		list.deleteCharAt(list.length() - 1);
		return ok(modifierListeChapitre.render(list.toString()));
	}

	/**
	 * Retourne la liste des Question suivant le chapitre
	 * 
	 * @param idChapitre
	 * @return
	 */
	public static Result getQuestion(final int idChapitre) {
		// Vérification sur le Statut du Utilisateur afficher que si Statut=Expert
		final long idUtilisateur = Long.parseLong(session().get("id"));
		final Utilisateur temp = Utilisateur.findById(idUtilisateur);

		if (temp.getStatut().equals(Statut.Etudiant)) {
			return ok(pageErreurConnexion.render());
		}
		final Long idL = (long) idChapitre;
		Chapitre c = new Chapitre();
		c = Chapitre.findById(idL);
		final List<Question> allQuestion = c.getSesQuestions();
		final StringBuilder list = new StringBuilder();
		for (int i = 0; i < allQuestion.size(); i++) {
			final Question q = allQuestion.get(i);
			list.append(q.getIdQuestion() + "#" + q.getLibelleQuestion() + ";");
		}
		list.deleteCharAt(list.length() - 1);
		return ok(modifierListeQuestion.render(list.toString()));
	}

	/**
	 * Retourne les commentaires de la question
	 * 
	 * @param idquestion
	 * @return
	 */
	public static Result getCommentaire(final int idquestion) {
		// Vérification sur le Statut du Utilisateur afficher que si Statut=Expert
		final long idUtilisateur = Long.parseLong(session().get("id"));
		final Utilisateur temp = Utilisateur.findById(idUtilisateur);

		if (temp.getStatut().equals(Statut.Etudiant)) {
			return ok(pageErreurConnexion.render());
		}

		final Long idL = (long) idquestion;
		Question q = new Question();
		q = Question.findById(idL);
		final StringBuilder list = new StringBuilder();
		list.append(q.getLibelleQuestion() + ";" + q.getCommentaire() + ";"
				+ q.getNiveauQuestion().getLibelleNiveau() + ";");
		final List<Choix> allChoix = q.getListeChoix();
		for (int i = 0; i < allChoix.size(); i++) {
			final Choix c = allChoix.get(i);
			list.append(c.getDescriptifChoix() + "#" + c.getEstVrai() + "#");
		}
		list.deleteCharAt(list.length() - 1);
		return ok(modifierCommentaireQuestion.render(list.toString()));
	}
}
